package com.xdxc.filter;

import com.xdxc.utils.IpAddressUtils;
import io.jsonwebtoken.io.IOException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Component
@RequiredArgsConstructor

@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE + 1) // 比最高优先级稍低
public class IpWhitelistFilter extends OncePerRequestFilter implements Ordered {

    @Value("#{'${security.allowed.ips:}'.split(',')}")
    private Set<String> allowedIps = new HashSet<>();
    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE + 1; // 最高优先级+1
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException, java.io.IOException {

        // 1. 放行公共端点
        if (isPublicEndpoint(request)) {
            filterChain.doFilter(request, response);
            return;
        }

        // 2. IP白名单检查
        String clientIp = IpAddressUtils.getClientIp(request);
        if (isIpAllowed(clientIp)) {
            // 设置属性标记跳过JWT验证
            request.setAttribute("IP_WHITELIST_PASSED", true);
            log.debug("IP whitelist access granted for {} to {}", clientIp, request.getRequestURI());
        }

        // 3. 无论是否白名单都继续后续流程
        filterChain.doFilter(request, response);
    }

    private boolean isPublicEndpoint(HttpServletRequest request) {
        String path = request.getRequestURI();
        return path.startsWith("/auth/") ;
    }

    private boolean isIpAllowed(String clientIp) {
        if (allowedIps.isEmpty()) return false;

        return allowedIps.stream()
                .anyMatch(ip -> ip.equals(clientIp) ||
                        IpAddressUtils.isInRange(clientIp, ip));
    }
}